package util.http.client5;

import java.util.concurrent.TimeUnit;

import org.apache.hc.client5.http.config.ConnectionConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;

public class HttpClient5Config {

	private static final long CONNECT_TIMEOUT = 8 * 1000L;
	private static final int SOCKET_TIMEOUT = 5 * 1000;
	private static final int CONNECTION_REQUEST_TIMEOUT = 8 * 1000;

	private static final int MAX_TOTAL = 500;
	private static final int DEFAULT_MAX_PER_ROUTE = 50;

	private RequestConfig requestConfig;
	private ConnectionConfig connectionConfig;
	private PoolingHttpClientConnectionManager connectionManager;
	private CloseableHttpClient closeableHttpClient;
	
	
	public HttpClient5Config() {
		this.requestConfig = initRequestConfig();
		this.connectionConfig = initConnectionConfig();
		this.connectionManager = initConnectionManager();

		createCloseableHttpClient();
	}

	private RequestConfig initRequestConfig() {

		RequestConfig requestConfigDefault = RequestConfig.DEFAULT;

		RequestConfig requestConfig = RequestConfig.copy(requestConfigDefault)
				.setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS)
				.setRedirectsEnabled(true).setCircularRedirectsAllowed(false).build();
		
		return requestConfig;

	}
	
	private ConnectionConfig initConnectionConfig() {
		
		ConnectionConfig connectionConfigDefault = ConnectionConfig.DEFAULT;
		
		ConnectionConfig connectionConfig = ConnectionConfig.copy(connectionConfigDefault)
				.setConnectTimeout(CONNECT_TIMEOUT,TimeUnit.MILLISECONDS)
				.setSocketTimeout(SOCKET_TIMEOUT,TimeUnit.MILLISECONDS).build();
		
		return connectionConfig;
		
	}

	private PoolingHttpClientConnectionManager initConnectionManager() {

		PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
		connectionManager.setMaxTotal(MAX_TOTAL);
		connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);
		connectionManager.setDefaultConnectionConfig(this.connectionConfig);
		
		return connectionManager;

	}

	private CloseableHttpClient initCloseableHttpClient() {

		HttpClientBuilder httpClientBuilder = HttpClients.custom().setConnectionManager(this.connectionManager);
		httpClientBuilder.setDefaultRequestConfig(this.requestConfig);

		return httpClientBuilder.build();
	}

	public void createCloseableHttpClient() {
		if (this.requestConfig != null && this.connectionManager != null) {
			this.closeableHttpClient = initCloseableHttpClient();
		}
	}
	
	
	public RequestConfig getRequestConfig() {
		return requestConfig;
	}

	public void setRequestConfig(RequestConfig requestConfig) {
		this.requestConfig = requestConfig;
	}

	public PoolingHttpClientConnectionManager getConnectionManager() {
		return connectionManager;
	}

	public void setConnectionManager(PoolingHttpClientConnectionManager connectionManager) {
		this.connectionManager = connectionManager;
	}

	public CloseableHttpClient getCloseableHttpClient() {
		return closeableHttpClient;
	}

	public void setCloseableHttpClient(CloseableHttpClient closeableHttpClient) {
		this.closeableHttpClient = closeableHttpClient;
	}

	public ConnectionConfig getConnectionConfig() {
		return connectionConfig;
	}

	public void setConnectionConfig(ConnectionConfig connectionConfig) {
		this.connectionConfig = connectionConfig;
	}

}
